/*
 * Copyright (c) 2007-2008, Thomas Krause (tho.krause@gmail.com)
 * 
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 * 
 *     * Redistributions of source code must retain the above copyright notice,
 *       this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright notice,
 *       this list of conditions and the following disclaimer in the documentation
 *       and/or other materials provided with the distribution.
 *     * Neither the name of gidoo nor the names of its contributors may be used to
 *       endorse or promote products derived from this software without specific
 *       prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.gidoo.cms.editor.edit;

import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.xml.XMLConstants;
import javax.xml.transform.stream.StreamSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import javax.xml.validation.Validator;
import org.apache.wicket.ajax.AjaxRequestTarget;
import org.apache.wicket.ajax.markup.html.form.AjaxButton;
import org.apache.wicket.ajax.markup.html.form.AjaxSubmitLink;
import org.apache.wicket.extensions.ajax.markup.html.modal.ModalWindow;
import org.apache.wicket.markup.html.basic.Label;
import org.apache.wicket.markup.html.form.Button;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.markup.html.panel.Panel;
import org.apache.wicket.model.Model;
import org.gidoo.cms.GidooCMS;
import org.gidoo.cms.editor.EditorPage;
import org.gidoo.cms.helper.Tools;
import org.gidoo.cms.jcr.JcrHelper;
import org.gidoo.cms.login.GidooCMSSession;
import org.gidoo.cms.view.XSLTTransformFailedException;
import org.xml.sax.SAXException;

/**
 *
 * @author thomas
 */
public class EditPanel extends Panel
{
  
  Form formEdit;
  
  Label lblStatus;
  TextField txtTitle;
  EditorComponent editorComponent;
  AjaxButton btOk;
  Button btAbort;
 
  AjaxSubmitLink lnkPreview;
  ModalWindow window;
  
  EditorPage parentPage;
  
  public EditPanel(String id, Node folder, EditorPage parent)
  {
    super(id);
   
    this.setOutputMarkupId(true);
    
    formEdit =new Form("formEdit");
    add(formEdit);
    
    lblStatus = new Label("lblStatus", new Model(""));
    try
    {
      editorComponent = 
        ((GidooCMS) getApplication()).getEditorComponent().newInstance();
    }
    catch(Exception ex)
    {
      Logger.getLogger(EditPanel.class.getName()).log(Level.SEVERE, getString("editorinstantfailed"), ex);
      error(getString("editorinstantfailed"));
      // fallback
      editorComponent = new SimpleEditorComponent();
    }
    
    txtTitle = new TextField("txtTitle", new Model(""));
    
    btOk =new AjaxButton("btOk")
    {
      @Override
      protected void onSubmit(AjaxRequestTarget target, Form form)
      {
        updateDB(target);
      }
    };
    btOk.setModel(new Model(getString("ok")));
    
    btAbort = new Button("btAbort");
    btAbort.setModel(new Model(getString("abort")));
    
    lnkPreview = new AjaxSubmitLink("lnkPreview") 
    {
      @Override
      protected void onSubmit(AjaxRequestTarget target, Form form)
      {
        final String content = editorComponent.getText();
        if(validate(content))
        {
        
          window.setPageCreator(new ModalWindow.PageCreator() 
          {

            public org.apache.wicket.Page createPage()
            {            
              try
              {              
                return new PreviewPage(content);
              }
              catch (XSLTTransformFailedException ex)
              {
                Logger.getLogger(EditPanel.class.getName()).log(Level.SEVERE, null, ex);
                error(getString("validationfailed"));
              }
              return null;
              
            }
          });
          
          window.setTitle(getString("preview") + ": " + txtTitle.getModelObjectAsString());
          window.show(target);
        }
        else
        {
          error(getString("validationfailed"));
        }
      
        
        target.addComponent(parentPage.getFeedbackPanel());
      }
    };
    
    lnkPreview.setVisible(editorComponent.isPreviewFunctionNeeded());
    
    formEdit.add(editorComponent);
    formEdit.add(txtTitle);
    formEdit.add(btOk);
    formEdit.add(btAbort);
    formEdit.add(lnkPreview);
    
    window = new ModalWindow("window");
    add(window);
    
    add(lblStatus);
    
    
    updateDataAndView(folder, parent);
    
    
  }
  
  private boolean validate(String newContent)
  {
    File f = new File(((GidooCMS) getApplication()).getRealPathToContext() 
      + "/WEB-INF/xml/markup.xsd");
    if(!f.exists())
    {
      error(getString("missingschemafile"));
      return false;
    }
    
    try
    {

      Schema s = 
        SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI).newSchema(f);

      StringReader reader = new StringReader(newContent);

      Validator validator = s.newValidator();
      StreamSource source = new StreamSource(reader);
      validator.validate(source);

    }
    catch (SAXException ex)
    {
      Logger.getLogger(EditPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("validationfailed"));
      error(ex.getLocalizedMessage());
      return false;
    }
    catch(IOException ex)
    {
      Logger.getLogger(EditPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("error"));
      return false;
    }
    
    return true;
  }
  
  public void updateDB(AjaxRequestTarget target)
  {
    Node theNode = parentPage.getCurrentSelectedPage();
    if (theNode == null || target == null)
    {
      return;
    }
   
    target.addComponent(parentPage.getFeedbackPanel());
    target.addComponent(parentPage.getTreeNav());

    String newContent = editorComponent.getText();

    if(!"".equals(newContent))
    {
      if(!validate(newContent))
        return;
    }
    
    try
    {
      GidooCMSSession session = (GidooCMSSession) getSession();
      Node rootNode = session.getJcrRootNode();
      String convertedPath = Tools.path2DraftName(theNode.getPath().substring(1));
      Node drafts = rootNode.getNode("drafts");
      // check for an old draft and remove it necessary
      if(drafts.hasNode(convertedPath))
      {
        Node oldDraft = drafts.getNode(convertedPath);
        oldDraft.remove();
      }
      
      // create new draft
      Node newDraft = drafts.addNode(convertedPath, theNode.getPrimaryNodeType().getName()); 
      
      newDraft.setProperty("cms:xml", newContent);
      newDraft.setProperty("cms:title", txtTitle.getModelObjectAsString());
      newDraft.setProperty("cms:editor", session.getUsername());
      newDraft.setProperty("cms:publisher", "");
      
      drafts.save();
      
      lblStatus.setModelObject(getString("waitingforpublisher"));
    }
    catch (RepositoryException ex)
    {
      Logger.getLogger(EditPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }


    parentPage.updateDataAndView();

  }

  public void updateDataAndView(Node page, EditorPage parent)
  {
    try
    {
      if (parent == null)
      {
        throw new NullPointerException();
      }

      parentPage = parent;

      editorComponent.setEnabled(true);
      editorComponent.enableComponents(true);

      btAbort.setEnabled(true);
      btOk.setEnabled(true);
      txtTitle.setEnabled(true);
      lnkPreview.setEnabled(true);

      Node drafts = ((GidooCMSSession) getSession()).getJcrRootNode().getNode("drafts");

      
      if(page == null)
      {
        lblStatus.setModelObject(getString("null"));
        editorComponent.setEnabled(false);
        editorComponent.enableComponents(false);

        btAbort.setEnabled(false);
        btOk.setEnabled(false);
        txtTitle.setEnabled(false);
        lnkPreview.setEnabled(false);
      }
      else if(drafts.hasNode(Tools.path2DraftName(page.getPath().substring(1))))
      {
        Node d = drafts.getNode(Tools.path2DraftName(page.getPath().substring(1)));
        lblStatus.setModelObject(getString("waitingforpublisher"));
        editorComponent.setText(d.getProperty("cms:xml").getString());
        txtTitle.setModelObject(d.getProperty("cms:title").getString());
      }
      else if(JcrHelper.isPublished(page))
      {
        lblStatus.setModelObject(getString("published"));
        editorComponent.setText(page.getProperty("cms:xml").getString());
        txtTitle.setModelObject(page.getProperty("cms:title").getString());
      }
      else
      {
        lblStatus.setModelObject(getString("isnew"));
        editorComponent.setEnabled(true);
        editorComponent.enableComponents(true);

        if ("".equals(editorComponent.getText()))
        {
          editorComponent.setText(getString("defaultxml"));
        }
      }
    }
    catch (RepositoryException ex)
    {
      Logger.getLogger(EditPanel.class.getName()).log(Level.SEVERE, null, ex);
      error(getString("jcrerror"));
    }
    
    
  }
  
}
